#include "blockqueue.hpp"
#include "Task.hpp"
#include <unistd.h>
#include <ctime>
#include <string>
#define CNUM 3
#define PNUM 5
const string opers = "+-*/%";
//typedef int Data;
typedef Task Data;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
bool isfree = true;

void* Consumer(void *args) //消费者
{
    BlockQueue<Data> *bq = static_cast<BlockQueue<Data>*>(args);
    while(true)
    {
        //1、消费者拿到数据
        Data t = Data(); //Data数据的默认值
        bq->Pop(&t);
        t();

        pthread_mutex_lock(&mutex); //显示器资源也是共享资源，访问显示器资源也需要上锁
        while(!isfree) 
            pthread_cond_wait(&cond, &mutex); 
        
        isfree = false;
        //cout << "消费者开始消费数据：" << d << " 消费者编号：" << pthread_self() << endl;
        std::cout << "处理任务: " << t.GetTask() << " 运算结果是：" 
            << t.GetResult() << " thread id: " << pthread_self() << std::endl;
        isfree = true;

        pthread_cond_signal(&cond); 
        pthread_mutex_unlock(&mutex);
        //2、处理数据
        usleep(100); //模拟处理数据


        // cout << "开始消费……" << endl;
        sleep(1);
    }
    return nullptr;
}

void* Productor(void *args) //生产者
{
    BlockQueue<Data> *bq = static_cast<BlockQueue<Data>*>(args);
    while(true)
    {
        //1、生产者拿到数据
        usleep(100); //模拟生产者拿数据
        Data t = Data(rand() % 10, opers[rand() % (opers.size())], rand() % 10);

        pthread_mutex_lock(&mutex);
        while(!isfree) 
            pthread_cond_wait(&cond, &mutex); 
        
        isfree = false;
        std::cout << "生产了一个任务: " << t.GetTask() << " thread id: " << pthread_self() << std::endl;
        isfree = true;
        
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);

        bq->Push(t);
        // cout << "开始生产……" << endl;
        sleep(1);
    }
    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr) ^ 0x35534d5);
    BlockQueue<Data> *bq = new BlockQueue<Data>(); //创建共享的资源

    //创建线程
    pthread_t c[CNUM], p[PNUM];
    for(int i = 0; i < CNUM; i++)
    {
        pthread_create(c + i, nullptr, Consumer, bq);
    }
    for(int i = 0; i < PNUM; i++)
    {
        pthread_create(p + i, nullptr, Productor, bq);
    }
    //线程等待
    for(int i = 0; i < CNUM; i++)
    {
        pthread_join(c[i], nullptr);
    }
    for(int i = 0; i < PNUM; i++)
    {
        pthread_join(p[i], nullptr);
    }

    delete bq;
    return 0;
}